package com.syyo.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.syyo.admin.domain.entity.NodeAttrEntity;
import com.syyo.admin.domain.entity.NodeChildEntity;
import com.syyo.admin.domain.entity.NodeConfigEntity;
import com.syyo.admin.domain.entity.UserEntity;
import com.syyo.admin.domain.req.NodeAttrReq;
import com.syyo.admin.domain.req.NodeChildReq;
import com.syyo.admin.domain.req.NodeConfigReq;
import com.syyo.admin.domain.resp.NodeChildResp;
import com.syyo.admin.mapper.*;
import com.syyo.admin.service.FlowService;
import com.syyo.admin.service.NodeAttrService;
import com.syyo.common.utils.MyListUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wang
 * @date 2021-04-09 11:34:57
 */
@Service
public class FlowServiceImpl extends ServiceImpl<NodeConfigMapper, NodeConfigEntity> implements FlowService {

    @Autowired
    private NodeConfigMapper nodeConfigMapper;

    @Autowired
    private NodeChildMapper nodeChildMapper;

    @Autowired
    private NodeAttrService nodeAttrService;

    @Autowired
    private NodeAttrMapper nodeAttrMapper;

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private DeptMapper newDeptMapper;


    /**
     * 新增
     *
     * @return ResultVo
     */
    @Override
    @Transactional
    public int add(NodeConfigReq req) {
        // 获取最新版本号
        Long version = nodeConfigMapper.findVersion(req.getTempType());
        if (version == null) {
            version = 1L;
        } else {
            version += 1;
        }
        req.setVersion(version);
        // 先添加节点
        NodeChildReq childNode = req.getChildNode();

        Integer nextId = addNodeRecursion(childNode, req.getTempType(), version);
        req.setNodeId(nextId);
        NodeConfigEntity nodeConfig = new NodeConfigEntity();
        BeanUtils.copyProperties(req, nodeConfig);
        int i = nodeConfigMapper.insert(nodeConfig);

        return i;
    }

    /**
     * 递归添加子节点
     *
     * @param node
     * @param tempType
     * @return
     */
    private Integer addNodeRecursion(NodeChildReq node, Integer tempType, Long version) {
        Integer type = node.getType();
        if (type == 4) { // 条件
            // 当前节点对象是条件,先处理下级节点，再处理条件
            NodeChildReq childNode = node.getChildNode();
            if (childNode != null) { // 当前条件节点有下级节点
                Integer nextId = addNodeRecursion(childNode, tempType, version);
                List<NodeChildReq> conditionNodes = node.getConditionNodes();
                List<Integer> conditionNodeIds = new ArrayList<>();
                for (NodeChildReq conditionNode : conditionNodes) {
                    if (conditionNode.getChildNode() == null) {
                        // 条件节点下面没有子节点，设置默认
                        addNodeChild(conditionNode, 0, tempType, null, version);
                        // 添加条件的属性
                        List<NodeAttrReq> nodeUserList = conditionNode.getNodeUserList();
                        if (MyListUtils.isNotEmpty(nodeUserList)) {
                            addNodeAttr(nodeUserList, conditionNode.getNodeId(), version);
                        }
                    } else {
                        // 条件下面有子节点
                        Integer conditionNextId = addNodeRecursion(conditionNode.getChildNode(), tempType, version);
                        addNodeChild(conditionNode, conditionNextId, tempType, null, version);
                        // 添加条件的属性
                        List<NodeAttrReq> nodeUserList = conditionNode.getNodeUserList();
                        if (MyListUtils.isNotEmpty(nodeUserList)) {
                            addNodeAttr(nodeUserList, conditionNode.getNodeId(), version);
                        }
                    }
                    conditionNodeIds.add(conditionNode.getNodeId());
                }
                String conditionNodeIdStr = MyListUtils.listToString(conditionNodeIds);
                addNodeChild(node, nextId, tempType, conditionNodeIdStr, version);


            } else { // 当前条件节点没有下级节点
                List<NodeChildReq> conditionNodes = node.getConditionNodes();
                List<Integer> conditionNodeIds = new ArrayList<>();
                for (NodeChildReq conditionNode : conditionNodes) {
                    if (conditionNode.getChildNode() == null) {
                        // 条件下面没有子节点
                        addNodeChild(conditionNode, 0, tempType, null, version);
                        // 添加条件的属性
                        List<NodeAttrReq> nodeUserList = conditionNode.getNodeUserList();
                        if (MyListUtils.isNotEmpty(nodeUserList)) {
                            addNodeAttr(nodeUserList, conditionNode.getNodeId(), version);
                        }
                    } else {
                        // 条件下面有子节点
                        Integer nextId = addNodeRecursion(conditionNode.getChildNode(), tempType, version);
                        addNodeChild(conditionNode, nextId, tempType, null, version);
                        // 添加条件的属性
                        List<NodeAttrReq> nodeUserList = conditionNode.getNodeUserList();
                        if (MyListUtils.isNotEmpty(nodeUserList)) {
                            addNodeAttr(nodeUserList, conditionNode.getNodeId(), version);
                        }
                    }
                    conditionNodeIds.add(conditionNode.getNodeId());
                }
                String conditionNodeIdStr = MyListUtils.listToString(conditionNodeIds);
                addNodeChild(node, 0, tempType, conditionNodeIdStr, version);
            }

        } else if (type == 1) {// 审批人
            // 当前节点对象是审批人
            NodeChildReq childNode = node.getChildNode();
            if (childNode != null) {
                // 有下级节点，先处理下级节点
                Integer nextId = addNodeRecursion(childNode, tempType, version);
                addNodeChild(node, nextId, tempType, null, version);
            } else {
                // 没有下级节点
                addNodeChild(node, 0, tempType, null, version);
            }

        } else if (type == 2) {// 抄送人
            // 当前节点对象是审批人
            NodeChildReq childNode = node.getChildNode();
            if (childNode != null) {
                // 有下级节点，先处理下级节点
                Integer nextId = addNodeRecursion(childNode, tempType, version);
                addNodeChild(node, nextId, tempType, null, version);
            } else {
                // 没有下级节点
                addNodeChild(node, 0, tempType, null, version);
            }
        }

        List<NodeAttrReq> nodeUserList = node.getNodeUserList();
        if (MyListUtils.isNotEmpty(nodeUserList)) {
            addNodeAttr(nodeUserList, node.getNodeId(), version);
        }
        return node.getNodeId();
    }

    /**
     * 添加节点
     */
    private void addNodeChild(NodeChildReq node, Integer nextId, Integer tempType, String conditionNodeIdStr, Long version) {
        node.setNextNode(nextId);
        node.setTempType(tempType);
        node.setNextConditionNodes(conditionNodeIdStr);
        node.setVersion(version);
        NodeChildEntity nodeChildEntity = new NodeChildEntity();
        BeanUtils.copyProperties(node, nodeChildEntity);
        nodeChildMapper.insert(nodeChildEntity);
        node.setNodeId(nodeChildEntity.getNodeId());
    }

    /**
     * 添加节点的属性
     */
    private void addNodeAttr(List<NodeAttrReq> list, Integer nodeId, Long version) {
        List<NodeAttrEntity> collect = list.stream().map(item -> {
            NodeAttrEntity attrEntity = new NodeAttrEntity();
            BeanUtils.copyProperties(item, attrEntity);
            attrEntity.setNodeId(nodeId);
            attrEntity.setVersion(version);
            return attrEntity;
        }).collect(Collectors.toList());
        nodeAttrService.saveBatch(collect);
    }

    /**
     * 详情
     *
     * @return ResultVo
     */
    @Override
    @Transactional
    public Map<String, Object> findOne(Integer tempType, Long version) {


        if (version == null) {
            version = nodeConfigMapper.findVersion(tempType);
        }
        NodeConfigEntity nodeConfig = nodeConfigMapper.selectOne(new QueryWrapper<NodeConfigEntity>().eq("temp_type", tempType).eq("version", version));

        if (nodeConfig != null) {
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("tempType", nodeConfig.getTempType());
            resultMap.put("type", nodeConfig.getType());
            resultMap.put("nodeName", nodeConfig.getNodeName());
            NodeChildResp nodeRecursion = findNodeRecursion(nodeConfig.getNodeId());
            resultMap.put("childNode", nodeRecursion);
            resultMap.put("version", version);
            return resultMap;
        }
        return null;
    }


    private NodeChildResp findNodeRecursion(Integer currentNodeId) {
        // 查询当前节点的的信息
        NodeChildEntity entity = nodeChildMapper.selectById(currentNodeId);
        NodeChildResp currentNode = new NodeChildResp();
        BeanUtils.copyProperties(entity, currentNode);

        Integer type = currentNode.getType();
        if (type == 1) { // 审批人
            // 查询审批人里的属性
            findAttr(currentNode);
            if (currentNode.getNextNode() == 0) {
                // 当前节点没有下一级，直接返回
                return currentNode;
            }
            // 有下一级，递归调用
            NodeChildResp nextNode = findNodeRecursion(currentNode.getNextNode());
            // 调用递归查询子节点的信息，把子节点对象添加到当前节点的子节点属性里
            currentNode.setChildNode(nextNode);

        } else if (type == 2) { // 抄送人
            // 查询抄送人里的属性
            findAttr(currentNode);
            if (currentNode.getNextNode() == 0) {
                // 当前节点没有下一级，直接返回
                return currentNode;
            }
            // 有下一级，递归调用
            NodeChildResp nextNode = findNodeRecursion(currentNode.getNextNode());
            currentNode.setChildNode(nextNode);

        } else if (type == 3) { // 条件，
            if (currentNode.getNextNode() == 0) {
                // 当前节点没有下一级，直接返回
                return currentNode;
            }
            // 有下一级，递归调用
            NodeChildResp nextNode = findNodeRecursion(currentNode.getNextNode());
            currentNode.setChildNode(nextNode);

        } else if (type == 4) { // 大条件，包含下级节点和下级条件节点
            // 先处理下级节点，
            String nextConditionNodes = currentNode.getNextConditionNodes();
            String[] split = nextConditionNodes.split(",");
            List<NodeChildResp> list = new ArrayList<>();

            if (currentNode.getNextNode() == 0) {
                // 当前节点没有下一级，
                for (int i = 0; i < split.length; i++) {
                    Integer nodeId = Integer.parseInt(split[i]);
                    NodeChildEntity entity1 = nodeChildMapper.selectById(nodeId);
                    NodeChildResp conditionNode = new NodeChildResp();
                    BeanUtils.copyProperties(entity1, conditionNode);
                    findAttr(conditionNode);
                    if (conditionNode.getNextNode() != 0) {
                        // 当前节点不是最后一级，递归调用
                        NodeChildResp nodeRecursion = findNodeRecursion(conditionNode.getNextNode());
                        conditionNode.setChildNode(nodeRecursion);
                    }
                    list.add(conditionNode);
                }
                // 把多个条件节点添加到当前节点对象里
                currentNode.setConditionNodes(list);
                return currentNode;
            }

            NodeChildResp nextNode = findNodeRecursion(currentNode.getNextNode());
            // 在处理条件节点
            for (int i = 0; i < split.length; i++) {
                Integer nodeId = Integer.parseInt(split[i]);
                NodeChildEntity entity1 = nodeChildMapper.selectById(nodeId);
                NodeChildResp conditionNode = new NodeChildResp();
                BeanUtils.copyProperties(entity1, conditionNode);
                findAttr(conditionNode);
                if (conditionNode.getNextNode() != 0) {
                    // 当前节点不是最后一级，递归调用
                    NodeChildResp nodeRecursion = findNodeRecursion(conditionNode.getNextNode());
                    conditionNode.setChildNode(nodeRecursion);
                }
                list.add(conditionNode);
            }
            // 把多个条件节点和下级节点设置到当前节点对象里
            currentNode.setChildNode(nextNode);
            currentNode.setConditionNodes(list);
        }
        return currentNode;
    }

    /**
     * 查询当前节点的属性，并添加进去
     *
     * @param node
     */
    private void findAttr(NodeChildResp node) {
        List<NodeAttrEntity> list = nodeAttrMapper.selectList(new QueryWrapper<NodeAttrEntity>().eq("node_id", node.getNodeId()));
        node.setNodeUserList(list);
    }

    @Override
    public Map<String, Object> matchTest(Integer userId, Integer tempType, Long version) {

        if (version == null) {
            version = nodeConfigMapper.findVersion(tempType);
        }
        NodeConfigEntity nodeConfig = nodeConfigMapper.selectOne(new QueryWrapper<NodeConfigEntity>().eq("temp_type", tempType).eq("version", version));

        if (nodeConfig != null) {
            Map<String, Object> resultMap = new HashMap<>();
            resultMap.put("tempType", nodeConfig.getTempType());
            resultMap.put("type", nodeConfig.getType());
            resultMap.put("nodeName", nodeConfig.getNodeName());
            NodeChildResp nodeRecursion = findNodeRecursion(nodeConfig.getNodeId());
            resultMap.put("childNode", nodeRecursion);
            resultMap.put("version", version);
            matchActivate(nodeRecursion, userId);

            return resultMap;
        }
        return null;
    }

    private void matchActivate(NodeChildResp node, Integer userId) {
        // 1.先查员工的基本信息
        // 1.1 查询员工的部门
        UserEntity sysUser = userMapper.selectById(userId);
        Integer currentDept = sysUser.getDeptId();// 部门
        // 判断子节点是否符合条件，符合就给个激活属性
        activateRecursion(node, userId, currentDept);

    }

    /**
     * 给匹配的节点添加激活属性 isActivate
     *
     * @param currentNode
     * @param currentDept
     */
    private void activateRecursion(NodeChildResp currentNode, Integer currentUserId, Integer currentDept) {
        Integer nodeType = currentNode.getType();
        Integer nextNodeId = currentNode.getNextNode();
        NodeChildResp nextNode = currentNode.getChildNode();
        if (nodeType == 1) { // 审批人
            currentNode.setIsActivate(true);
            if (nextNodeId != 0) {
                // 当前节点有下一级，递归调用
                activateRecursion(nextNode, currentUserId, currentDept);
            }
        } else if (nodeType == 2) { // 抄送人
            currentNode.setIsActivate(true);
            if (nextNodeId != 0) {
                // 当前节点有下一级，递归调用
                activateRecursion(nextNode, currentUserId, currentDept);
            }
        } else if (nodeType == 3) { // 条件
            currentNode.setIsActivate(true);
            if (nextNodeId != 0) {
                // 当前节点有下一级，递归调用
                activateRecursion(nextNode, currentUserId, currentDept);
            }
        } else if (nodeType == 4) { // 大条件
            List<NodeChildResp> conditionNodes = currentNode.getConditionNodes();
            for (NodeChildResp conditionNode : conditionNodes) {
                boolean ismatch = isMatch(conditionNode.getNodeId(), currentUserId, currentDept);
                if (ismatch) {
                    // 符合条件，进入这个条件分支的节点
                    activateRecursion(conditionNode, currentUserId, currentDept);
                    break;
                }
            }
            if (nextNodeId != 0) {
                // 当前节点有下一级，递归调用
                activateRecursion(nextNode, currentUserId, currentDept);
            }
        }
    }

    /**
     * 判断是否符合条件
     *
     * @param conditionNodeId
     * @return
     */
    private boolean isMatch(Integer conditionNodeId,
                            Integer currentUserId,
                            Integer currentDept) {
        // 当前节点有下一级，判断是否满足条件，满足就进入下个节点，不满足直接返回
        int deptCount = 0;//记录部门类型的条件个数
        boolean isDept = false;//部门类型条件的状态
        int empCount = 0;//记录员工类型的条件个数
        boolean isEmp = false;//员工类型条件的状态
        List<NodeAttrEntity> attrs = nodeAttrMapper.selectList(new QueryWrapper<NodeAttrEntity>().eq("node_id", conditionNodeId));
        for (NodeAttrEntity attr : attrs) {
            Integer type = attr.getType();
            if (type == 101) { // 部门
                deptCount++;
                // 部门的判断方式
                Integer deptId = Integer.parseInt(attr.getTargetId());
                // 查询当前部门的子部门
                List<Integer> ziDept = newDeptMapper.getChildren(deptId);
                if (currentDept.equals(deptId) || ziDept.contains(currentDept)) {
                    isDept = true;
                }
            } else { // 104：人
                // 员工的判断方式
                empCount++;
                String targetId = attr.getTargetId();
                int userId = Integer.parseInt(targetId);
                if (currentUserId == userId) {
                    isEmp = true;
                }
            }
        }
        // 部门类型个数 为0，默认满足这个条件
        if (deptCount == 0) {
            isDept = true;
        }

        // 员工类型个数 为0，默认满足这个条件
        if (empCount == 0) {
            isEmp = true;
        }

        // 满足，进入当前节点的下一级
        return isDept && isEmp;
    }


}